#include "stdafx.h"
#include "GameEngine.h"

#include "IGame.h"
#include "IKeyboardNotification.h"

#include "SDLGameWindow.h"

namespace AGE
{
	GameEngine::GameEngine( IGame& iGame ) : m_game ( iGame ),
										   m_pGameWindow ( nullptr )
	{
	}


	GameEngine::~GameEngine()
	{
		delete m_pGameWindow;
	}

	bool GameEngine::InitSDL()
	{
		bool fSuccess = true;

		if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER ) != 0 )
		{
			//SDL_GetError();
			fSuccess = false;
		}

		m_pGameWindow = new SDLGameWindow();

		if ( m_pGameWindow )
		{
			fSuccess = m_pGameWindow->Init();
		}
		else
		{
			fSuccess = false;
		}

		atexit(SDL_Quit);

		return fSuccess;
	}

	void GameEngine::Start()
	{
		const int TICKS_PER_SECOND = 25;
		const int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
		const int MAX_FRAMESKIP = 5;

		Uint32 next_game_tick = SDL_GetTicks();
		int loops;
		float interpolation;

		if ( InitSDL() )
		{
			m_game.Init( this );

			bool game_is_running = true;
			SDL_Event evt;
			Sint32 mouseX, mouseY;
			Vector2D<Uint32> mousePosition;
			Vector2D<Sint32> mouseRelativePosition;

			while( game_is_running ) 
			{
				loops = 0;

				while( SDL_GetTicks() > next_game_tick && loops < MAX_FRAMESKIP ) 
				{
					//Find out which keys are down
					m_game.SetKeyState( SDL_GetKeyState( NULL ) );
					m_game.SetMouseState( SDL_GetMouseState( &mouseX, &mouseY ) );
					
					while ( SDL_PollEvent(&evt) ) 
					{
						switch (evt.type) 
						{  
							case SDL_KEYUP:
								m_game.OnKeyUp(evt.key.keysym.sym);
								break;
							case SDL_KEYDOWN:
								m_game.OnKeyDown(evt.key.keysym.sym);
								break;  							
							case SDL_MOUSEMOTION:
								mousePosition.Set(evt.motion.x, 480 -evt.motion.y);
								mouseRelativePosition.Set(evt.motion.xrel, -evt.motion.yrel);
								m_game.OnMouseMotion(mousePosition, mouseRelativePosition); 
								break;
							case SDL_MOUSEBUTTONDOWN:
								mousePosition.Set(evt.motion.x, 480 - evt.motion.y);
								m_game.OnMouseButtonDown(evt.button.button, mousePosition);
								break;
							case SDL_MOUSEBUTTONUP:
								m_game.OnMouseButtonUp(evt.button.button, mousePosition);
								break;
							case SDL_QUIT:
								game_is_running = false;
								break;
						}				
					}
					m_game.Update();

					next_game_tick += SKIP_TICKS;
					loops++;
				}

				interpolation = float( SDL_GetTicks() + SKIP_TICKS - next_game_tick ) / float( SKIP_TICKS );
				m_game.Render(interpolation);
			}

			m_game.Destroy();
		}
	}
}
